package com.yansl.sensitive.core;

import java.io.IOException;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.yansl.http.handler.SpringHandler;
import com.yansl.sensitive.annotation.Enc;
import com.yansl.sensitive.constant.EncTypeEnum;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @description: 核心处理类
 * @author: yansl.cn
 * @create: 2023-01-10 11:08
 */
@Slf4j
public class EncCoreHandler extends JsonSerializer<String> implements ContextualSerializer {

    public IEncDefaultHandler encDefaultHandler = (IEncDefaultHandler) SpringHandler.getByType(IEncDefaultHandler.class);

    /**
     * 字段类型
     */
    private JavaType fieldType;
    /**
     * 字段名称
     */
    private String fieldName;

    /**
     * 注解对象
     */
    private Enc annotation;

    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(annotation.type() == EncTypeEnum.SYS_ENC ? autoTransfor(value)
                        : encDefaultHandler.transfor(annotation, fieldType, fieldName, value));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) throws JsonMappingException {
        this.annotation = property.getAnnotation(Enc.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
            this.fieldName = property.getName();
            this.fieldType = property.getType();

            return this;
        }
        return serializerProvider.findValueSerializer(property.getType(), property);
    }

    /**
     * 自动转换，自动加密
     * 
     * @param value
     * @return
     */
    public String autoTransfor(String value) {
        int before = annotation.before();
        int after = annotation.after();
        char symbol = annotation.symbol();

        boolean isBeyond = (before + after) > value.length();

        // 超出长度，全部加密
        if (isBeyond) {
            return StrUtil.replace(value, 0, value.length(), symbol);
        }
        // 未超出长度
        return StrUtil.replace(value, before, value.length() - after, symbol);
    }
}
